/*
*  This file is part of mangusta
*
*  mangusta is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  mangusta is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with mangusta; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  US
*
*  Author: <antonino.calderone@ericsson.com>, <acaldmail@gmail.com>
*
*/


/* -------------------------------------------------------------------------- */

#ifndef __NU_PROG_POINTER_H__
#define __NU_PROG_POINTER_H__

#include <deque>
#include <sstream>
#include <string>


/* -------------------------------------------------------------------------- */

namespace nu
{

/* -------------------------------------------------------------------------- */

class prog_pointer_t
{
public:
   using line_number_t = unsigned int;
   using stmt_number_t = unsigned int;

   prog_pointer_t(
      line_number_t line = 0,
      stmt_number_t stmt = 0) throw()
      :
      _line(line),
      _line_stmt(stmt)
   {}

   prog_pointer_t(const prog_pointer_t&) = default;
   prog_pointer_t& operator=(const prog_pointer_t&) = default;


   void go_to(line_number_t line, stmt_number_t stmt = 0) throw()
   {
      set(line, stmt);
   }


   void set(line_number_t line, stmt_number_t stmt) throw()
   {
      _line = line;
      _line_stmt = stmt;
   }


   void set_stmt_pos(stmt_number_t stmt)
   {
      _line_stmt = stmt;
   }


   line_number_t get_line() const throw()
   {
      return _line;
   }


   int get_stmt_pos() const throw()
   {
      return _line_stmt;
   }


   void reset() throw()
   {
      set(0, 0);
   }


   bool operator<(const prog_pointer_t& pp) const throw()
   {
      return _line > pp._line || (_line == pp._line && _line_stmt > pp._line_stmt);
   }


   std::string to_string() const throw()
   {
      return std::to_string(_line) + ":" + std::to_string(_line_stmt);
   }

private:
   line_number_t _line = 0;
   stmt_number_t _line_stmt = 0;
};


/* -------------------------------------------------------------------------- */

struct return_stack_t :
   public std::deque <
   std::pair< prog_pointer_t::line_number_t, size_t > >
{
   void trace(std::stringstream& ss);
};
}


/* -------------------------------------------------------------------------- */

#endif // __NU_PROG_POINTER_H__